package com.example.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.backend.common.api.ResultCode;
import com.example.backend.common.exception.BusinessException;
import com.example.backend.dto.PasswordDTO;
import com.example.backend.dto.ProfileDTO;
import com.example.backend.dto.UserDTO;
import com.example.backend.entity.Role;
import com.example.backend.entity.User;
import com.example.backend.entity.UserRole;
import com.example.backend.mapper.UserMapper;
import com.example.backend.mapper.UserRoleMapper;
import com.example.backend.service.RoleService;
import com.example.backend.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 用户服务实现类
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    
    private final PasswordEncoder passwordEncoder;
    private final UserRoleMapper userRoleMapper;
    private final RoleService roleService;

    @Override
    public User getByUsername(String username) {
        return baseMapper.selectUserWithRolesAndPermissions(username);
    }
    
    @Override
    public boolean createUser(UserDTO userDTO) {
        // 1. 检查用户名是否存在
        if (checkUsernameExists(userDTO.getUsername())) {
            throw new BusinessException(ResultCode.USERNAME_EXISTS);
        }
        
        // 2. 检查邮箱是否存在
        if (checkEmailExists(userDTO.getEmail())) {
            throw new BusinessException(ResultCode.EMAIL_EXISTS);
        }
        
        // 3. 创建用户实体
        User user = new User();
        user.setUsername(userDTO.getUsername());
        user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        user.setNickname(userDTO.getNickname());
        user.setEmail(userDTO.getEmail());
        user.setPhone(userDTO.getPhone());
        user.setStatus(userDTO.getStatus() != null ? userDTO.getStatus() : 1);
        
        // 4. 保存用户
        if (!save(user)) {
            throw new BusinessException(ResultCode.FAILED);
        }
        
        // 5. 分配角色
        if (userDTO.getRoleIds() != null && !userDTO.getRoleIds().isEmpty()) {
            List<UserRole> userRoles = userDTO.getRoleIds().stream()
                    .map(roleId -> {
                        UserRole userRole = new UserRole();
                        userRole.setUserId(user.getId());
                        userRole.setRoleId(roleId);
                        return userRole;
                    })
                    .toList();
            
            if (userRoleMapper.insertBatch(userRoles) <= 0) {
                throw new BusinessException(ResultCode.FAILED);
            }
        }
        
        return true;
    }
    
    @Override
    public boolean updateUser(UserDTO userDTO) {
        // 1. 检查用户是否存在
        User existingUser = getById(userDTO.getId());
        if (existingUser == null) {
            throw new BusinessException(ResultCode.USER_NOT_FOUND);
        }
        
        // 2. 如果修改了用户名，检查是否存在
        if (StringUtils.hasText(userDTO.getUsername()) 
                && !existingUser.getUsername().equals(userDTO.getUsername()) 
                && checkUsernameExists(userDTO.getUsername())) {
            throw new BusinessException(ResultCode.USERNAME_EXISTS);
        }
        
        // 3. 如果修改了邮箱，检查是否存在
        if (StringUtils.hasText(userDTO.getEmail()) 
                && !existingUser.getEmail().equals(userDTO.getEmail()) 
                && checkEmailExists(userDTO.getEmail())) {
            throw new BusinessException(ResultCode.EMAIL_EXISTS);
        }
        
        // 4. 更新用户信息，只更新非空字段
        User user = new User();
        user.setId(userDTO.getId());
        
        if (StringUtils.hasText(userDTO.getUsername())) {
            user.setUsername(userDTO.getUsername());
        }
        if (StringUtils.hasText(userDTO.getNickname())) {
            user.setNickname(userDTO.getNickname());
        }
        if (StringUtils.hasText(userDTO.getEmail())) {
            user.setEmail(userDTO.getEmail());
        }
        if (StringUtils.hasText(userDTO.getPhone())) {
            user.setPhone(userDTO.getPhone());
        }
        if (userDTO.getStatus() != null) {
            user.setStatus(userDTO.getStatus());
        }
        if (StringUtils.hasText(userDTO.getPassword())) {
            user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        }
        
        // 5. 保存更新
        if (!updateById(user)) {
            throw new BusinessException(ResultCode.FAILED);
        }
        
        // 6. 如果提供了角色ID，则更新角色关系
        if (userDTO.getRoleIds() != null) {
            // 先删除原有角色
            userRoleMapper.delete(new LambdaQueryWrapper<UserRole>()
                    .eq(UserRole::getUserId, user.getId()));
            
            // 添加新角色
            if (!userDTO.getRoleIds().isEmpty()) {
                List<UserRole> userRoles = userDTO.getRoleIds().stream()
                        .map(roleId -> {
                            UserRole userRole = new UserRole();
                            userRole.setUserId(user.getId());
                            userRole.setRoleId(roleId);
                            return userRole;
                        })
                        .toList();
                
                if (userRoleMapper.insertBatch(userRoles) <= 0) {
                    throw new BusinessException(ResultCode.FAILED);
                }
            }
        }
        
        return true;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUser(Long userId) {
        // 1. 检查用户是否存在
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_FOUND);
        }
        
        // 2. 删除用户角色关联
        userRoleMapper.delete(new LambdaQueryWrapper<UserRole>()
                .eq(UserRole::getUserId, userId));
        
        // 3. 删除用户
        return removeById(userId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(Long userId, String newPassword) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        user.setPassword(passwordEncoder.encode(newPassword));
        return updateById(user);
    }
    
    /**
     * 检查邮箱是否存在
     */
    @Override
    public boolean checkEmailExists(String email) {
        return count(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, email)) > 0;
    }
    
    /**
     * 检查用户名是否存在
     */
    @Override
    public boolean checkUsernameExists(String username) {
        return count(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)) > 0;
    }

    @Override
    public ProfileDTO getProfile(Long userId) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_FOUND);
        }
        
        ProfileDTO profile = new ProfileDTO();
        profile.setId(user.getId());
        profile.setNickname(user.getNickname());
        profile.setEmail(user.getEmail());
        profile.setPhone(user.getPhone());
        profile.setAvatar(user.getAvatar());
        return profile;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateProfile(ProfileDTO profileDTO) {
        // 1. 检查邮箱是否被其他用户使用
        if (checkEmailExists(profileDTO.getEmail(), profileDTO.getId())) {
            throw new BusinessException(ResultCode.EMAIL_EXISTS);
        }
        
        // 2. 更新用户信息
        User user = new User();
        user.setId(profileDTO.getId());
        user.setNickname(profileDTO.getNickname());
        user.setEmail(profileDTO.getEmail());
        user.setPhone(profileDTO.getPhone());
        user.setAvatar(profileDTO.getAvatar());
        
        return updateById(user);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePassword(Long userId, PasswordDTO passwordDTO) {
        // 1. 校验新密码与确认密码是否一致
        if (!passwordDTO.getNewPassword().equals(passwordDTO.getConfirmPassword())) {
            throw new BusinessException(ResultCode.PASSWORD_CONFIRM_ERROR);
        }
        
        // 2. 校验原密码是否正确
        User user = getById(userId);
        if (!passwordEncoder.matches(passwordDTO.getOldPassword(), user.getPassword())) {
            throw new BusinessException(ResultCode.OLD_PASSWORD_ERROR);
        }
        
        // 3. 更新密码
        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setPassword(passwordEncoder.encode(passwordDTO.getNewPassword()));
        
        return updateById(updateUser);
    }

    @Override
    public User getByPhone(String phone) {
         return getOne(new LambdaQueryWrapper<User>()
                .eq(User::getPhone, phone));
    }

    /**
     * 检查邮箱是否存在(排除自己)
     */
    private boolean checkEmailExists(String email, Long userId) {
        return count(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, email)
                .ne(User::getId, userId)) > 0;
    }
} 